package mxmf;

import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

import chances.smart.commons.MVCConfigure;
import chances.smart.commons.aspect.log.LogAspect;
import chances.smart.commons.aspect.validator.ValidAspect;
import chances.smart.commons.compare.config.ConfigCompareController;
import chances.smart.commons.compare.db.DataSourceCompareController;
import chances.smart.commons.jpa.mvc.EntityBindAdvice;
import chances.smart.commons.jpa.query.SmartJpaRepositoryFactoryBean;
import chances.smart.commons.jpa.query.config.SmartJpaConfig;
import chances.smart.commons.mvc.ExceptionHandle;
import chances.smart.commons.mvc.interceptor.AccessTokenConfig;
import chances.smart.commons.mvc.interceptor.AccessTokenInterceptor;
import mxmf.utils.ObjectMapperHelper;

@Configuration
@Import({ MVCConfigure.class, ExceptionHandle.class, ValidAspect.class, EntityBindAdvice.class,
        LogAspect.class, SmartJpaConfig.class, DataSourceCompareController.class,
        ConfigCompareController.class })
@EnableJpaRepositories(repositoryFactoryBeanClass = SmartJpaRepositoryFactoryBean.class)
public class CmsWebConfig implements WebMvcConfigurer {

    @Value("${chances.auth.key:87651234}")
    String authKey;

    @Value("${chances.auth.ignore-path:actuator,browser,error}")
    String ignorePath;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        AccessTokenConfig config = new AccessTokenConfig(authKey);
        config.addIgnorePaths(ignorePath.split(","));
        HandlerInterceptor interceptor = new AccessTokenInterceptor(config);
        registry.addInterceptor(interceptor);
    }
    

    @Bean
    public FilterRegistrationBean<OpenEntityManagerInViewFilter> openEntityManagerInViewFilter() {
        FilterRegistrationBean<OpenEntityManagerInViewFilter> registration = new FilterRegistrationBean<OpenEntityManagerInViewFilter>(
                new OpenEntityManagerInViewFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }


    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Iterator<HttpMessageConverter<?>> iterator = converters.iterator();
        while (iterator.hasNext()) {
            HttpMessageConverter<?> converter = iterator.next();
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                iterator.remove();
            }
        }
        ObjectMapper objectMapper = ObjectMapperHelper.createObjectMapper();
        objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, true);
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);

        MappingJackson2HttpMessageConverter convert = new MappingJackson2HttpMessageConverter(
                objectMapper);

        converters.add(convert);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new PageableHandlerMethodArgumentResolver());
    }

}
